package com.nancy.java_design.singleton.demo5;

/**
 * 单例模式
 * 懒汉式 ：双重检锁机制+vilatile
 */
public class Singleton {
    // 1.私有化构造方法
    private Singleton() {
    }

    // 2.创建私有化对象,使用volatile关键字保证可见性和有序性，保证线程安全，防止指令重排
    private static volatile Singleton instance;

    // 3.提供公共方法
    public static Singleton getInstance() {
        // 如果不是null，直接返回，不需要加锁，提高效率
        if (instance == null) {
            // 如果为null，需要加锁，保证线程安全
            //线程1到这里开始继续往下执行,线程2,3等待
            synchronized (Singleton.class) {
                // 再次判断，防止多线程同时进入
                /**
                 * 第二次判断是为了避免以下情况的发生。
                 *
                 * 线程1到这里发现instance为空，继续执行if代码块，执行完成后退出同步区域，
                 * 然后线程2进入同步代码块，如果在这里不再加一次判断，
                 * 就会造成instance再次实例化，由于增加了判断，线程2到这里发现instance已被实例化于是就跳过了if代码块,
                 * 防止在此处实例化，从而避免了重复实例化
                 */
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}
